/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Modelo;

/**
 *
 * @author vanesa
 */
public class TableroInicial9x9 {
    
    private static int [][] tablero=new int[9][9];
    private static int []fila=new int[9];
    private static int []columna=new int [9];
    private static int [] valores= new int [9];
    SolucionTablero9x9 s= new SolucionTablero9x9();
    
    public TableroInicial9x9(int [][] tablero){
        for(int i=0;i<9;i++)
            for(int j=0;j<9;j++){
                tablero[i][j]=0;
                this.tablero[i][j]=0;
            }
    }
    
    public TableroInicial9x9(){}
    
    /**
     * Método que se encarga de generar números aleatorios
     * mayores o iguales a cero y menores a seis.
     * @param v "Arreglo a que van a ir a parar los valores de los indices
     * para inicializar el tablero inicial del juego"
     * @return int [][] "retorna el array con los números aleatorios generado."
     */
    public int[] generarArraysAleatoriosIndices(int [] v){
	int i,j;
        
	for(i=0;i<v.length;i++){
		v[i]=(int)(Math.random()*10);
                    for(j=0;j<i;j++){
                            if((v[i]==v[j])||(v[i]==v.length)){
                                    i--;
                            }
                    }
	}
        return v;
    }
    
    /**
     * Método que se encarga de generar números aleatorios
     * mayores a cero y menores o iguales a seis.
     * @param v "Arreglo a que van a ir a parar los valores para inicializar
     * el tablero inicial del juego"
     * @return int [][] "retorna el array con los números aleatorios generado."
     */
    public int[] generarArrayValoresAleatorios(int [] v){
	int i,j;
        
	for(i=0;i<v.length;i++){
		v[i]=(int)(Math.random()*10);
                    for(j=0;j<i;j++){
                            if((v[i]==v[j])||(v[i]==0)){
                                    i--;
                            }
                    }
	}
        return v;
    }
    
    /**VerificarColumna: Este método se encarga de verificar que el valor a ingresar
     * en el tablero no este en la columna.
     * @param tablero "Tablero de la partida en estado actual del juego."
     * @param valor "Valor a chequear que no se repita en la columna."
     * @param fila "Entero que representa la fila en donde se va a colocar ese 
     * valor a verificar en la columan."
     * @return boolean "Retorna true si ese valor pasado como parámetro
     * ya se encuentra en la columna, de lo contrario retorna false."
     */
    public boolean VerificarColumna(int [][] tablero, int valor, int fila){
		boolean esta= false;
		int i=0;
		while((i<tablero.length)&&(!esta)){
			if (valor == tablero [fila][i])
				esta=true;
			i++;
		}
		return esta;
	}
	
	/**VerificarFila: Este método se encarga de verificar que el valor a ingresar
     * en el tablero no este en la fila.
     * @param tablero "Tablero de la partida en estado actual del juego."
     * @param valor "Valor a chequear que no se repita en la fila."
     * @param columna "Entero que representa la columna en donde se va a colocar ese 
     * valor a verificar en la fila."
     * @return boolean "Retorna true si ese valor pasado como parámetro
     * ya se encuentra en la fila, de lo contrario retorna false."
     */
	public boolean VerificarFila(int [][] tablero, int valor, int columna){
		boolean esta= false;
		int i=0;
		while((i<tablero.length)&&(!esta)){
			if (valor == tablero [i][columna])
				esta=true;
			i++;
		}
		return esta;
	}
        /**VerificarCuadricula: Este método se encarga de verificar que el valor a ingresar
     * en el tablero no este en la cuadricula en la que va a ser ingresado.
     * @param tablero "Tablero de la partida en estado actual del juego."
     * @param valor "Valor a chequear que no se repita en la fila."
     * @param columna "Entero que representa la columna en donde se va a colocar ese 
     * valor a verificar en la cuadricula."
     * @param fila "Entero que representa la fila en donde se va a colocar ese 
     * valor a verificar en la cuadricula."
     * @return boolean "Retorna true si ese valor pasado como parámetro
     * ya se encuentra en la cuadricula, de lo contrario retorna false."
     */
        public boolean VerificarCuadricula(int [][] tablero, int fila, int columna, int valor){
            boolean esta=false;
            int i= (fila / 3)*3;
            int j= (columna / 3)*3;
            int m=i+3;
            int n=j+3;
            for(int k=i;k<m;k++)
                for(int l=j;l<n;l++){
                    if(tablero[k][l]==valor)
                        esta=true;}
            
            return esta;
        }
    
    
     /**
     * Método que genera el tablero inicial del juego Sudoku, con dimención 9x9.
     * @param cantInicial "Número de elementos que inicializarán el tablero."
     * @return int[][] "retorna el una matriz inicializada con valores entre 0 y 6."
     */
    public int[][] generarTableroIni(int cantInicial){
        fila=this.generarArraysAleatoriosIndices(fila);
        columna=this.generarArraysAleatoriosIndices(columna);
        valores=this.generarArrayValoresAleatorios(valores);
        boolean ctrlCol= false;
        boolean ctrlFila=false;
        boolean ctrlCuad=false;
        int i=0;
        int j=0;
        try{
        while(cantInicial>0){
            if(i<8) i++; 
            else {
                i=0;
                fila=this.generarArraysAleatoriosIndices(fila);
                columna=this.generarArraysAleatoriosIndices(columna);
            }
            if(j<8) j++; else j=0;
            //System.out.println(j+" otro indice: "+i+" valor "+valores[j]);
            ctrlCol= (!(this.VerificarColumna(tablero,valores[j] ,fila[i])));
            ctrlFila= (!(this.VerificarFila(tablero,valores[j] ,columna[i])));
            ctrlCuad= (!(this.VerificarCuadricula(tablero,fila[i],columna[i],valores[j])));
            if ((!ctrlCol)&&(!ctrlFila)&&(!ctrlCuad)){
                tablero[fila[i]][columna[i]]=valores[j];
                cantInicial--;
            }
            else{
                     if(!(this.VerificarColumna(tablero,valores[i] ,columna[j]))&&
                       (!(this.VerificarFila(tablero,valores[i] ,fila[i])))&&
                       (!(this.VerificarCuadricula(tablero,columna[j],fila[i],valores[i])))){
                            tablero[columna[j]][fila[i]]=valores[i];
                            cantInicial--;
                    }
                 }
                
            }
        }catch(Exception ex){
            this.generarTableroIni(cantInicial);
        }
                
        
        return tablero;
    }
    
    /**Metodo que se encarga de verificar si el tablero inicial generado
    * tiene solución, en caso de no ternerla, genera un nuevo tablero y si 
    * éste tiene solución lo retorna.
    * @param cantInicial "Número de elementos que inicializarán el tablero."
    * @return int[][] "retorna el una matriz inicializada con valores entre 0 y 6."
    */
   public int[][] generarTablero(int cantInicial){
        int [][]aux= new int [9][9];
          aux=this.generarTableroIni(cantInicial);
          Verificar verificar= new Verificar(aux);
          if(verificar.SolEqualIni(aux)){
              for(int i=0;i<9;i++)
                for(int j=0;j<9;j++){
                    aux[i][j]=0;
                }
              generarTablero(cantInicial);
          }
          return aux;
   }
    
    public static void main (String [] args){
         int [][] tab=new int[9][9];
         TableroInicial9x9 p= new TableroInicial9x9(tab);
         tab=p.generarTablero(17);
         for(int i=0;i<tab.length;i++){
            for(int j=0;j<tab[0].length;j++)
                System.out.print(tab[i][j]+"|");
         System.out.println();}
            
         }

}